/******************************************************************************
 * Copyright (C) 2013 ShenZhen ComTop Information Technology Co.,Ltd
 * All Rights Reserved.
 * 本软件为深圳康拓普开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、
 * 复制、修改或发布本软件.
 *****************************************************************************/

package com.code.common.util;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;


/**
 * 汉字转拼音服务类
 * <pre>
 * 辅助ChineseUtil完成其功能：通过CommonDAO获取Connection，使用存储过程进行转化
 * </pre>
 * @see ChineseUtil
 * 
 * @author 陈星凌
 * @since TOP4.0
 * @version 2013-2-1 陈星凌 新建
 */
@Service
public final class ChineseConvertService {
    
    /** 日志对象 */
    protected final static Logger LOGGER = LoggerFactory.getLogger(ChineseConvertService.class);
    
    /** commonDAO,用于获取数据库连接 */
    @Resource
    //private CommonDAO commonDAO;
    
    /** 全拼缓存Map对象，在内存中存储已获取过的结果 */
    private static final Map<String, String> fullSpellMap = new HashMap<String, String>(2000);
    
    /** 首字母拼音缓存Map对象，在内存中存储已获取过的结果 */
    private static final Map<String, String> firstSpellMap = new HashMap<String, String>(2000);
    
    /** 每晚23:00-24:00间，对map对象进行一次清理 */
    private static Thread cacheMaintance;
    
    /**
     * 维护用于缓存的两个map对象
     * <pre>
     * 每次从map里读取数据后会执行此方法，目前的策略是：每晚23:00-24:00间，对map对象进行一次清理。
     * </pre>
     */
    private void maintanceCache() {
        if (cacheMaintance == null) {
            cacheMaintance = new CacheClearThread();
            cacheMaintance.setDaemon(true);
            cacheMaintance.start();
        }
    }
    
    /**
     * 构造函数
     */
    private ChineseConvertService() {
    }
    
    /**
     * 返回字符串的全拼,仅中文汉字转化为全拼,其它字符不进行转换
     * 
     * <pre>
     *  若存在多音字或方言,会以“;”分隔每一种读音情况
     * </pre>
     * 
     * @param cnStr String 包含中文汉字的字符串
     * @return String 转换成全拼后的字符串
     */
    public String getFullSpell(String cnStr) {
        String strResult = getFullSpellFromCache(cnStr);
        if (strResult == null) {
            strResult = getFullSpellFromDataBase(cnStr);
            fullSpellMap.put(cnStr, strResult);
        }
        return strResult;
    }
    
    /**
     * 获取汉语字符串的声母组合，每个汉字取拼音的第一个字符组成的一个字符串
     * 
     * <pre>
     *  若存在多音字或方言,会以“;”分隔每一种读音情况<br>
     *  如“了解”，返回值为“liaojie;lejie”
     * </pre>
     * 
     * @param cnStr 汉字的字符串
     * @return 每个汉字拼音的第一个字母所组成的字符串
     */
    public String getFirstSpell(String cnStr) {
        String strResult = getFirstSpellFromCache(cnStr);
        if (strResult == null) {
            strResult = getFirstSpellFromDataBase(cnStr);
            firstSpellMap.put(cnStr, strResult);
        }
        return strResult;
    }
    
    /**
     * 从缓存（服务器内存中的Map）中获取全拼
     * 
     * @param cnStr 待转化字符
     * @return 转换结果
     */
    private String getFullSpellFromCache(String cnStr) {
        return fullSpellMap.get(cnStr);
    }
    
    /**
     * 从数据库中获取全拼
     * 
     * @param cnStr 待转化字符
     * @return 转换结果
     */
    private String getFullSpellFromDataBase(String cnStr) {
        String strResult = null;
        try {
//            Connection conn = commonDAO.getConnection();
//            CallableStatement cs = conn.prepareCall("{ ?=call f_getHZPYSpell(?,?) }");
//            cs.setString(2, cnStr);
//            cs.setInt(3, 0);
//            cs.registerOutParameter(1, java.sql.Types.VARCHAR);
//            cs.execute();
//            strResult = cs.getString(1);
        } catch (Exception sqle) {
            LOGGER.error("获取hibernate连接时出错:" + sqle);
        }
        maintanceCache();
        return strResult;
    }
    
    /**
     * 从缓存（服务器内存中的Map）中获取首字母拼音
     * 
     * @param cnStr 待转化字符
     * @return 转换结果
     */
    private String getFirstSpellFromCache(String cnStr) {
        return firstSpellMap.get(cnStr);
    }
    
    /**
     * 从数据库中获取首字母拼音
     * 
     * @param cnStr 待转化字符
     * @return 转换结果
     */
    private String getFirstSpellFromDataBase(String cnStr) {
        String strResult = null;
        try {
//            Connection conn = commonDAO.getConnection();
//            CallableStatement cs = conn.prepareCall("{ ?=call f_getHZPYSpell(?,null) }");
//            cs.setString(2, cnStr);
//            cs.registerOutParameter(1, java.sql.Types.VARCHAR);
//            cs.execute();
//            strResult = cs.getString(1);
        } catch (Exception sqle) {
            LOGGER.error("获取hibernate连接时出错:" + sqle);
        }
        maintanceCache();
        return strResult;
    }
    
    /**
     * 本线程用于清除缓存在内存里的拼音字符转化数据。
     * 
     * <pre>
     *  每晚23:00-24:00的某个时间清理（取决于服务启动的时间）
     * </pre>
     * 
     * @author 陈星凌
     * @since 1.0
     * @version 2013-2-4 陈星凌
     */
    static class CacheClearThread extends Thread {
        
        /**
         * 清除缓存在内存里的拼音字符转化数据。
         */
        @Override
        public void run() {
            while (true) {
                try {
                    TimeUnit.HOURS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 每天23点-24点时间段内清空Map中的值。
                if (Calendar.getInstance().get(Calendar.HOUR_OF_DAY) == 23) {
                    fullSpellMap.clear();
                    firstSpellMap.clear();
                }
            }
        }
    }
    
}